"use client"; import { use } from "react"; import Link from "next/link"; import { useApi } from "@/lib/api"; import { fmtDate } from "@/lib/format"; import { Bar, Empty, Metric, Panel, Skeleton, Table, Tag } from "@/components/ui"; interface Detail { platform: string; summary: { confidence: number; page_types: number; entity_types: number; navigation_actions: number; network_schemas: number; media_patterns: number; sessions: number } | null; model: { updated_at: string; response_patterns: Record; observed_count: number; entity_yield_total: number; confidence: number; triggered_by: Record; first_seen: string; last_seen: string }>; action_patterns: Record; failures: number }>; page_types: Record; avg_entities: number; entity_types: Record; avg_confidence: number }>; media_patterns: Record; sessions_learned: string[]; } | null; manifest: { compiled_at: string; confidence: number; network_patterns: unknown[] } | null; profiles: { alias: string; has_state: boolean }[]; } export default function PlatformPage({ params }: { params: Promise<{ platform: string }> }) { const { platform } = use(params); const { data, loading } = useApi(`/platforms/${platform}`, { refreshMs: 15_000 }); if (loading) return ; if (!data) return unknown platform; const m = data.model; const rps = m ? Object.values(m.response_patterns).filter((r) => Object.keys(r.likely_entity_types).length).sort((a, b) => b.confidence - a.confidence) : []; const aps = m ? Object.values(m.action_patterns).filter((a) => a.from_page_type !== "ANY").sort((a, b) => b.observed_count - a.observed_count) : []; const pts = m ? Object.values(m.page_types).sort((a, b) => b.observed_count - a.observed_count) : []; return (
connectors / {platform}

{platform}

{data.summary && (
confidence = 70 ? "#43e69a" : "#38e1ff"} /> {data.summary.confidence}%
)}
{!m ? ( Nothing learned yet on {platform}. {["youtube", "reddit"].includes(platform) ? "Launch a learning mission from the Missions page." : "No adapter yet — this platform is scheduled for a later phase."} ) : ( <>
`${p.alias}${p.has_state ? " ✓" : ""}`).join(", ") : "none — run pnpm login"} />
{pts.map((p) => ( ))}
{p.page_type} {p.observed_count} {p.avg_entities.toFixed(1)} {p.avg_confidence.toFixed(2)} {Object.entries(p.url_patterns) .sort((a, b) => b[1] - a[1]) .slice(0, 3) .map(([k, v]) => `${k} (${v})`) .join(" ")} {Object.entries(p.entity_types) .sort((a, b) => b[1] - a[1]) .slice(0, 4) .map(([k, v]) => ( {k} {v} ))}
{rps.length ? ( {rps.map((r) => ( ))}
{r.method} {r.hostname} {r.path_pattern} {r.graphql_operation && {r.graphql_operation}}
#{r.shape_hash.slice(0, 10)}
{Object.entries(r.likely_entity_types).map(([t, n]) => ( {t} {n} ))} {Object.entries(r.triggered_by).map(([a, n]) => ( {a.toLowerCase()} {n} ))} {r.observed_count} {(r.entity_yield_total / Math.max(1, r.observed_count)).toFixed(1)} ent/resp = 0.5 ? "#43e69a" : "#ffb347"} />
{r.confidence.toFixed(2)}
) : ( no entity-bearing schema learned yet )}
{aps.map((a) => ( ))}
{a.action_type.toLowerCase()} {a.from_page_type} {Object.entries(a.to_page_types) .sort((x, y) => y[1] - x[1]) .map(([k, v]) => `${k} ${v}`) .join(", ")} {a.observed_count} {a.avg_new_entities.toFixed(1)} {a.avg_network_responses.toFixed(1)} {a.failures}
{Object.values(m.media_patterns).length ? ( {Object.values(m.media_patterns) .sort((a, b) => b.observed_count - a.observed_count) .map((mp) => ( ))}
{mp.hostname} {mp.kind} {mp.observed_count}
) : ( none yet )}
)}
); }